﻿using System;
using System.Web;
using System.Web.UI;
using System.Xml;
using System.Text;

namespace gms.data {
	public class AjaxManager : Page {
		private XmlDocument final_output;

		public AjaxManager() {
			// Ajax manager acts as a page, but it will only ever return XML
			this.Init += new EventHandler(AjaxManager_Init);
			this.Load += new EventHandler(AjaxManager_Load);
			this.Error += new EventHandler(AjaxManager_Error);
		}

		private void CreateNewDocument() {
			// Creates the header information for the XML document. I did
			// this to simply cut down on code amount
			final_output = new XmlDocument();

			XmlDeclaration xmldec = final_output.CreateXmlDeclaration("1.0", "utf-8", "yes");
			final_output.AppendChild(xmldec);
		}

		private void AjaxManager_Init(object sender, EventArgs e) {
			// With no post information, user must be visiting directly. Slap their wrists!
			if (Request.Form.Count == 0) {
				throw new Exception("You may not visit this page directly! It is used solely for the response to AJAX Queries sent by the application.");
			}

			// Post information is there, but no opcode field. BIG no no. Slap their wrists!
			if (Request.Form["opcode"] == null) {
				throw new Exception("The Ajax Manager must receive an opcode to handle what function is to be run.");
			}

			// Opcode field present, but its empty. Slap the programmers wrists!
			if (Request.Form["opcode"].Length == 0) {
				throw new Exception("The Op Code must contain a value.");
			}
		}

		private void AjaxManager_Load(object sender, EventArgs e) {
			CreateNewDocument();

			// All the magical science of the ajax processing happens in OpcodeManager
			// This file just creates and delivers the final XML
			XmlElement return_value = OpcodeManager.execute_code(Request.Form["opcode"], Request.Form["args"]);

			final_output.AppendChild(final_output.ImportNode(return_value, true));

			Response.HeaderEncoding = Encoding.UTF8;
			Response.ContentType = "text/xml";
			Response.StatusCode = 200;
			Response.Write(final_output.OuterXml);
			//Response.End();
			Response.Flush();
			//Context.ApplicationInstance.CompleteRequest();
		}

		private void AjaxManager_Error(object sender, EventArgs e) {
			CreateNewDocument();

			// Upon any error with the ajax or the processing thereof, this will
			// trigger. It will send back the message, stacktrace, and the
			// inner exception message and stacktrace if present. Cause we're that
			// good!
			Exception last_error = Server.GetLastError();

			XmlElement err_root = final_output.CreateElement("error");
			XmlElement err_message = final_output.CreateElement("message");
			XmlElement err_stack = final_output.CreateElement("stacktrace");
			XmlElement err_inner = final_output.CreateElement("innerexception");

			XmlCDataSection cdata_message = final_output.CreateCDataSection(last_error.Message);
			XmlCDataSection cdata_stack = final_output.CreateCDataSection(last_error.StackTrace);
			XmlCDataSection cdata_inner = final_output.CreateCDataSection((last_error.InnerException != null) ? last_error.InnerException.Message + " " + last_error.InnerException.StackTrace : "null");

			final_output.AppendChild(err_root);

			err_root.AppendChild(err_message);
			err_root.AppendChild(err_stack);
			err_root.AppendChild(err_inner);

			err_message.AppendChild(cdata_message);

			err_stack.AppendChild(cdata_stack);

			err_inner.AppendChild(cdata_inner);

			Response.Clear();
			Response.HeaderEncoding = Encoding.UTF8;
			Response.ContentType = "text/xml";
			Response.StatusCode = 200;
			Response.Write(final_output.OuterXml);
			//Response.End();
			Response.Flush();
			//Context.ApplicationInstance.CompleteRequest();
		}
	}
}